<template>
  <view class="image-preview-container" v-if="visible" @touchmove.stop.prevent>
    <!-- 遮罩层 -->
    <view class="mask" @click="close"></view>
    
    <!-- 图片预览区域 -->
    <view class="preview-content">
      <!-- 图片容器 -->
      <view class="image-area" @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd">
        <view 
          class="image-movable" 
          :style="{ 
            transform: `translate(${imageX}px, ${imageY}px) scale(${scale}) rotate(${rotate}deg)`,
            transition: isMoving || isScaling ? 'none' : 'transform 0.3s ease'
          }"
        >
          <image 
            class="preview-image" 
            :src="imageUrl" 
            mode="aspectFit"
            @load="onImageLoad"
            @error="onImageError"
          />
        </view>
      </view>
      
      <!-- 顶部导航栏 -->
      <view class="top-navbar">
        <view class="nav-back" @click="close">
          <text class="nav-icon">✕</text>
        </view>
        <view class="nav-title" v-if="imageList.length > 1">
          {{ currentIndex + 1 }} / {{ imageList.length }}
        </view>
        <view class="nav-title" v-else>
          图片预览
        </view>
        <view class="nav-actions">
          <text class="nav-icon" @click="saveImage">↓</text>
        </view>
      </view>
      
      <!-- 操作工具栏 -->
      <view class="toolbar">
        <view class="toolbar-item" @click="rotateLeft">
          <text class="icon-text">↺</text>
          <text class="toolbar-text">左转</text>
        </view>
        
        <view class="toolbar-item" @click="zoomOut">
          <text class="icon-text">−</text>
          <text class="toolbar-text">缩小</text>
        </view>
        
        <view class="toolbar-item" @click="reset">
          <text class="icon-text">↺</text>
          <text class="toolbar-text">重置</text>
        </view>
        
        <view class="toolbar-item" @click="zoomIn">
          <text class="icon-text">+</text>
          <text class="toolbar-text">放大</text>
        </view>
        
        <view class="toolbar-item" @click="rotateRight">
          <text class="icon-text">↻</text>
          <text class="toolbar-text">右转</text>
        </view>
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'

// 定义 props
const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false
  },
  urls: {
    type: Array,
    default: () => []
  },
  current: {
    type: [String, Number],
    default: 0
  }
})

// 定义 emits
const emit = defineEmits(['update:modelValue', 'close'])

// 响应式数据
const visible = ref(false)
const imageList = ref([])
const currentIndex = ref(0)
const scale = ref(1)
const imageX = ref(0)
const imageY = ref(0)
const rotate = ref(0)
const isMoving = ref(false)
const isScaling = ref(false)
const startX = ref(0)
const startY = ref(0)
const startImageX = ref(0)
const startImageY = ref(0)
const startScale = ref(1)
const minScale = ref(0.5)
const maxScale = ref(3)
const imageWidth = ref(0)
const imageHeight = ref(0)

// 计算属性
const imageUrl = computed(() => {
  return imageList.value[currentIndex.value] || ''
})

// 监听 modelValue 变化
watch(() => props.modelValue, (newVal) => {
  visible.value = newVal
  if (newVal) {
    initPreview()
  }
})

// 监听 urls 变化
watch(() => props.urls, (newVal) => {
  imageList.value = [...newVal]
}, { immediate: true })

// 初始化预览
const initPreview = () => {
  imageList.value = [...props.urls]
  
  // 确定当前图片索引
  if (typeof props.current === 'number') {
    currentIndex.value = props.current
  } else if (typeof props.current === 'string') {
    const index = imageList.value.indexOf(props.current)
    currentIndex.value = index > -1 ? index : 0
  }
  
  // 重置状态
  reset()
}

// 图片加载完成
const onImageLoad = (e) => {
  const { width, height } = e.detail
  imageWidth.value = width
  imageHeight.value = height
  resetPosition()
}

// 图片加载失败
const onImageError = (e) => {
  console.error('图片加载失败:', e)
  uni.showToast({
    title: '图片加载失败',
    icon: 'none'
  })
}

// 重置位置
const resetPosition = () => {
  imageX.value = 0
  imageY.value = 0
}

// 触摸开始
const handleTouchStart = (e) => {
  if (e.touches.length === 1) {
    // 单指触摸，用于移动
    isMoving.value = true
    startX.value = e.touches[0].pageX
    startY.value = e.touches[0].pageY
    startImageX.value = imageX.value
    startImageY.value = imageY.value
  } else if (e.touches.length === 2) {
    // 双指触摸，用于缩放
    isMoving.value = false
    isScaling.value = true
    startScale.value = scale.value
    
    // 计算初始双指间距
    const x1 = e.touches[0].pageX
    const y1 = e.touches[0].pageY
    const x2 = e.touches[1].pageX
    const y2 = e.touches[1].pageY
    const distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
    startX.value = distance
  }
}

// 触摸移动
const handleTouchMove = (e) => {
  if (isMoving.value && e.touches.length === 1) {
    // 单指移动
    const deltaX = e.touches[0].pageX - startX.value
    const deltaY = e.touches[0].pageY - startY.value
    imageX.value = startImageX.value + deltaX
    imageY.value = startImageY.value + deltaY
  } else if (isScaling.value && e.touches.length === 2) {
    // 双指缩放
    const x1 = e.touches[0].pageX
    const y1 = e.touches[0].pageY
    const x2 = e.touches[1].pageX
    const y2 = e.touches[1].pageY
    const distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
    
    // 计算缩放比例
    const scaleRatio = distance / startX.value
    const newScale = startScale.value * scaleRatio
    scale.value = Math.min(Math.max(newScale, minScale.value), maxScale.value)
  }
}

// 触摸结束
const handleTouchEnd = () => {
  isMoving.value = false
  isScaling.value = false
}

// 放大
const zoomIn = () => {
  scale.value = Math.min(scale.value + 0.2, maxScale.value)
}

// 缩小
const zoomOut = () => {
  scale.value = Math.max(scale.value - 0.2, minScale.value)
}

// 左旋转
const rotateLeft = () => {
  rotate.value = rotate.value - 90
}

// 右旋转
const rotateRight = () => {
  rotate.value = rotate.value + 90
}

// 重置
const reset = () => {
  scale.value = 1
  rotate.value = 0
  imageX.value = 0
  imageY.value = 0
}

// 保存图片
const saveImage = () => {
  // #ifdef H5
  uni.showToast({
    title: '请长按图片保存',
    icon: 'none'
  })
  // #endif
  
  // #ifndef H5
  // 检查图片URL是否有效
  if (!imageUrl.value) {
    uni.showToast({
      title: '图片地址无效',
      icon: 'none'
    })
    return
  }
  
  // 检查是否是网络图片
  if (imageUrl.value.startsWith('http')) {
    // 下载网络图片后再保存
    downloadAndSaveImage()
  } else {
    // 本地图片直接保存
    performSaveImage(imageUrl.value)
  }
  // #endif
}

// 下载并保存网络图片
const downloadAndSaveImage = () => {
  uni.showLoading({
    title: '下载中...'
  })
  
  // 下载图片
  uni.downloadFile({
    url: imageUrl.value,
    success: (res) => {
      if (res.statusCode === 200) {
        // 下载成功，保存到相册
        performSaveImage(res.tempFilePath)
      } else {
        uni.hideLoading()
        uni.showToast({
          title: '下载失败',
          icon: 'none'
        })
      }
    },
    fail: (err) => {
      uni.hideLoading()
      console.error('下载失败:', err)
      uni.showToast({
        title: '下载失败',
        icon: 'none'
      })
    }
  })
}

// 执行保存图片操作
const performSaveImage = (filePath) => {
  // 检查权限
  uni.getSetting({
    success: (res) => {
      if (!res.authSetting['scope.writePhotosAlbum']) {
        // 请求权限
        uni.authorize({
          scope: 'scope.writePhotosAlbum',
          success: () => {
            // 用户已授权，保存图片
            doSaveImage(filePath)
          },
          fail: () => {
            // 用户拒绝授权，引导用户手动授权
            uni.hideLoading()
            uni.showModal({
              title: '保存图片需要授权',
              content: '请在设置中允许访问相册',
              confirmText: '去设置',
              cancelText: '取消',
              success: (modalRes) => {
                if (modalRes.confirm) {
                  uni.openSetting()
                }
              }
            })
          }
        })
      } else {
        // 已有权限，直接保存图片
        doSaveImage(filePath)
      }
    },
    fail: () => {
      // 获取权限信息失败，尝试直接保存
      doSaveImage(filePath)
    }
  })
}

// 实际执行保存操作
const doSaveImage = (filePath) => {
  uni.saveImageToPhotosAlbum({
    filePath: filePath,
    success: () => {
      uni.hideLoading()
      uni.showToast({
        title: '保存成功',
        icon: 'success'
      })
    },
    fail: (err) => {
      uni.hideLoading()
      console.error('保存失败:', err)
      // 根据错误信息给出提示
      let errMsg = '保存失败'
      if (err.errMsg && err.errMsg.includes('auth')) {
        errMsg = '请允许访问相册权限'
      } else if (err.errMsg && err.errMsg.includes('fail')) {
        errMsg = '保存失败，请重试'
      }
      uni.showToast({
        title: errMsg,
        icon: 'none'
      })
    }
  })
}

// 关闭预览
const close = () => {
  visible.value = false
  emit('update:modelValue', false)
  emit('close')
}

// 键盘事件处理
const handleKeydown = (e) => {
  if (!visible.value) return
  
  switch (e.keyCode) {
    case 27: // ESC键
      close()
      break
    case 37: // 左箭头
      prevImage()
      break
    case 39: // 右箭头
      nextImage()
      break
    case 107: // +键
    case 187: // +键
      zoomIn()
      break
    case 109: // -键
    case 189: // -键
      zoomOut()
      break
  }
}

// 上一张图片
const prevImage = () => {
  if (currentIndex.value > 0) {
    currentIndex.value--
    reset()
  }
}

// 下一张图片
const nextImage = () => {
  if (currentIndex.value < imageList.value.length - 1) {
    currentIndex.value++
    reset()
  }
}

// 组件挂载时添加键盘事件监听
onMounted(() => {
  // #ifdef H5
  document.addEventListener('keydown', handleKeydown)
  // #endif
})

// 组件卸载时移除键盘事件监听
onUnmounted(() => {
  // #ifdef H5
  document.removeEventListener('keydown', handleKeydown)
  // #endif
})

// 初始化
if (props.modelValue) {
  initPreview()
}
</script>

<style lang="scss" scoped>
.image-preview-container {
  position: fixed;
  top: 86px;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9999;
}

.mask {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.95);
}

.preview-content {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
}

.image-area {
  flex: 1;
  width: 100%;
  height: 100%;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.image-movable {
  width: fit-content;
  height: fit-content;
  transform-origin: center center;
}

.preview-image {
  max-width: 100%;
  max-height: 100%;
}

.top-navbar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 88rpx;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 30rpx;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0.7), transparent);
  z-index: 10;
  
  .nav-back, .nav-actions {
    width: 80rpx;
    height: 80rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    transition: background-color 0.3s;
    
    &:active {
      background-color: rgba(255, 255, 255, 0.2);
    }
  }
  
  .nav-icon {
    font-size: 36rpx;
    color: #fff;
    font-weight: bold;
  }
  
  .nav-title {
    color: #fff;
    font-size: 32rpx;
    font-weight: 500;
    flex: 1;
    text-align: center;
    margin: 0 20rpx;
  }
}

.toolbar {
  position: absolute;
  bottom: 60rpx;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(20rpx);
  border-radius: 50rpx;
  padding: 20rpx 40rpx;
  display: flex;
  gap: 40rpx;
  box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.3);
  
  .toolbar-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    cursor: pointer;
    transition: transform 0.2s;
    padding: 10rpx 20rpx;
    border-radius: 20rpx;
    
    &:active {
      transform: scale(0.9);
      background-color: rgba(255, 255, 255, 0.1);
    }
    
    .icon-text {
      font-size: 40rpx;
      color: #fff;
      font-weight: bold;
      line-height: 1;
    }
    
    .toolbar-text {
      font-size: 20rpx;
      color: #fff;
      margin-top: 10rpx;
      line-height: 1;
    }
  }
}
</style>